23. JSON 序列化
📝 模块更新日志 新特性*
+ 新增 `JSON` 序列化支持设置 `DateOnly` 和 `TimeOnly` 类型格式化 4\.9\.3\.9 ⏱️2024\.05\.21 [\#I9QZKQ](https://gitee.com/dotnetchina/Furion/issues/I9QZKQ)
+ 新增 `JSON.IsValid(jsonString)` 判断 `JSON` 字符串有效性 4\.9\.1\.8 ⏱️2023\.11\.30 [22bc69b](https://gitee.com/dotnetchina/Furion/commit/22bc69bd4a445f81833c082da7c99f4a5c518012)
+ 新增 时间戳模型绑定器将时间戳转换为 `DateTime/DateTimeOffset` 类型 4\.9\.1\.5 ⏱️2023\.11\.20 [df3053c](https://gitee.com/dotnetchina/Furion/commit/df3053cf081d5e4d8eb63d567ed95c45267e0969)
+ 新增 `Newtonsoft.Json` 自动将时间戳转换为 `DateTime/DateTimeOffset` 类型 4\.9\.1\.3 ⏱️2023\.11\.17 [78a589d](https://gitee.com/dotnetchina/Furion/commit/78a589d99eb5985b576e4c96acd6e4890391d6ff)
+ 新增 `System.Text.Json` 自动将时间戳转换为 `DateTime/DateTimeOffset` 类型 4\.9\.1\.2 ⏱️2023\.11\.17 [abd5196](https://gitee.com/dotnetchina/Furion/commit/abd5196f5c5160a5df96dad80c7c5aa51b96d5b9)
+ 新增 `System.Text.Json` 和 `Newtonsoft.Json` 对粘土对象 `Clay` 支持 4\.8\.8\.1 ⏱️2023\.04\.18 [\#I6WKRZ](https://gitee.com/dotnetchina/Furion/issues/I6WKRZ)
-
突破性变化
- 调整
IJsonSerializerProvider序列化接口,添加Deserialize反序列化方法 4.8.8.15 ⏱️2023.05.15 !815 感谢 @YaChengMu
- 调整
查看变化添加 25-32行 接口方法:
namespace Furion.JsonSerialization;
/// <summary>
/// Json 序列化提供器
/// </summary>
public interface IJsonSerializerProvider
{
/// <summary>
/// 序列化对象
/// </summary>
/// <param name="value"></param>
/// <param name="jsonSerializerOptions"></param>
/// <returns></returns>
string Serialize(object value, object jsonSerializerOptions = default);
/// <summary>
/// 反序列化字符串
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="json"></param>
/// <param name="jsonSerializerOptions"></param>
/// <returns></returns>
T Deserialize<T>(string json, object jsonSerializerOptions = default);
/// <summary>
/// 反序列化字符串
/// </summary>
/// <param name="json"></param>
/// <param name="returnType"></param>
/// <param name="jsonSerializerOptions"></param>
/// <returns></returns>
object Deserialize(string json, Type returnType, object jsonSerializerOptions = default);
/// <summary>
/// 返回读取全局配置的 JSON 选项
/// </summary>
/// <returns></returns>
object GetSerializerOptions();
}
如果使用 Newtonsoft.Json 则只需添加以下实现即可:
/// <summary>
/// 反序列化字符串
/// </summary>
/// <param name="json"></param>
/// <param name="returnType"></param>
/// <param name="jsonSerializerOptions"></param>
/// <returns></returns>
public object Deserialize(string json, Type returnType, object jsonSerializerOptions = null)
{
return JsonConvert.DeserializeObject(json, returnType, (jsonSerializerOptions ?? GetSerializerOptions()) as JsonSerializerSettings);
}
-
问题修复
- 修复
DateTime/DateTimeOffset使用UTC时间不能正确JSON序列化为本地时间问题 4.9.4.6 ⏱️2024.07.16 b72bf7e - 修复 粘土对象序列化后出现二次序列化成字符串问题 4.9.2.4 ⏱️2024.04.02 fcb1223
- 修复 在
.NET8之后修改System.Text.Json默认序列化选项引发This JsonSerializerOptions instance is read-only or has already been used in serialization or deserialization.异常问题 4.9.2.2 ⏱️2024.03.29 9f44653 - 修复 在
Newtonsoft序列化中启用了AddLongTypeConverters配置来处理值类型被声明为可空类型并赋予默认值时出现转换异常问题 4.9.1.48 ⏱️2024.03.13 ecd547f - 修复
DateTime/DateTimeOffset/DateOnly/TimeOnly默认格式配置无效问题 4.9.1.30 ⏱️2024.02.07 8057a6a -
其他更改
-
调整 默认
System.Text.Json序列化提供器选项为不区分大小写匹配 4.9.2.1 ⏱️2024.03.29 b58e7be
- 修复
版本说明以下内容仅限 Furion 1.16.0 + 版本使用。
23.1 什么是 JSON
JSON (JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式。它基于 ECMAScript (w3c 制定的 js 规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
简单来说,JSON,是一种数据格式,在与后端的数据交互中有较为广泛的应用。
23.2 关于序列化库
目前在 C# 语言中有两个主流的 JSON 序列化操作库:
System.Text.Json:.NET Core内置JSON序列化库,也是Furion框架默认实现Newtonsoft.Json:目前使用人数最多的JSON序列化库,需要安装Microsoft.AspNetCore.Mvc.NewtonsoftJson拓展包
由于目前 System.Text.Json 相比 Newtonsoft.Json 功能和稳定性有许多不足之处,比如循环引用问题在 System.Text.Json 无解。但在 .NET 6 之后得到解决。
Furion 框架为了解决多种序列化工具配置和用法上的差异问题,抽象出了 IJsonSerializerProvider 接口。
23.3 IJsonSerializerProvider 接口
Furion 框架提供了 IJsonSerializerProvider 接口规范,同时要求实现该接口的实体都必须采用单例模式,该接口定义代码如下:
namespace Furion.JsonSerialization;
/// <summary>
/// Json 序列化提供器
/// </summary>
public interface IJsonSerializerProvider
{
/// <summary>
/// 序列化对象
/// </summary>
/// <param name="value"></param>
/// <param name="jsonSerializerOptions"></param>
/// <returns></returns>
string Serialize(object value, object jsonSerializerOptions = default);
/// <summary>
/// 反序列化字符串
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="json"></param>
/// <param name="jsonSerializerOptions"></param>
/// <returns></returns>
T Deserialize<T>(string json, object jsonSerializerOptions = default);
/// <summary>
/// 反序列化字符串
/// </summary>
/// <param name="json"></param>
/// <param name="returnType"></param>
/// <param name="jsonSerializerOptions"></param>
/// <returns></returns>
object Deserialize(string json, Type returnType, object jsonSerializerOptions = default);
/// <summary>
/// 返回读取全局配置的 JSON 选项
/// </summary>
/// <returns></returns>
object GetSerializerOptions();
}
默认实现SystemTextJsonSerializerProvider 类是 IJsonSerializerProvider 接口的默认实现,在应用启动时已默认注册。
23.4 如何使用
23.4.1 获取序列化对象
Furion 框架提供了两种方式获取 IJsonSerializerProvider 实例:
- 构造函数注入
IJsonSerializerProvider - 静态类
JSON.GetJsonSerializer()方式,查看 JSON 静态类
如:
using Furion.DynamicApiController;
using Furion.JsonSerialization;
namespace Furion.Application
{
public class JsonDemo : IDynamicApiController
{
private readonly IJsonSerializerProvider _jsonSerializer;
private readonly IJsonSerializerProvider _jsonSerializer2;
public JsonDemo(IJsonSerializerProvider jsonSerializer)
{
_jsonSerializer = jsonSerializer;
_jsonSerializer2 = JSON.GetJsonSerializer();
}
}
}
23.4.2 序列化对象
public string GetText()
{
return _jsonSerializer.Serialize(new
{
Id = 1,
Name = "Furion"
});
}
23.4.3 反序列化字符串
public object GetObject()
{
var json = "{\"Id\":1,\"Name\":\"Furion\"}";
var obj = _jsonSerializer.Deserialize<object>(json);
return obj;
}
特别注意System.Text.Json 默认反序列化大小写敏感,也就是不完全匹配的属性名称不会自动赋值。这时候我们可以全局配置或单独配置。
- 全局配置
services.AddControllersWithViews()
.AddJsonOptions(options => {
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
});
- 单独配置
var obj = _jsonSerializer.Deserialize<object>(json, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
23.4.4 序列化更多配置
Furion 框架不推荐一个框架中有多种序列化实现类,也就是说使用 System.Text.Json 就不要使用 Newtonsoft.Json,反之亦然。
如需配置更多选项,只需创建 JsonSerializerOptions 配置对象即可,如:
var json = _jsonSerializer.Serialize(new
{
Id = 1,
Name = "Furion"
}, new JsonSerializerOptions {
WriteIndented = true
});
23.5 高级用法
23.5.1 自定义序列化提供器
正如上文所说,Furion 默认的 IJsonSerializerProvider 实现方式是 System.Text.Json 库,如需替换为 Newtonsoft.Json,只需以下步骤即可:
无需安装在 Furion 4.6.5+ 版本已经内置了 Microsoft.AspNetCore.Mvc.NewtonsoftJson 拓展包,也就是直接在 Startup.cs 中注册即可。
- 安装
Microsoft.AspNetCore.Mvc.NewtonsoftJson拓展,并在Startup.cs中注册
services.AddControllersWithViews()
.AddNewtonsoftJson();
- 实现
IJsonSerializerProvider提供器
using Furion.JsonSerialization;
using Newtonsoft.Json;
namespace Furion.Core;
/// <summary>
/// Newtonsoft.Json 实现
/// </summary>
public class NewtonsoftJsonSerializerProvider : IJsonSerializerProvider, ISingleton
{
/// <summary>
/// 序列化对象
/// </summary>
/// <param name="value"></param>
/// <param name="jsonSerializerOptions"></param>
/// <returns></returns>
public string Serialize(object value, object jsonSerializerOptions = null)
{
return JsonConvert.SerializeObject(value, (jsonSerializerOptions ?? GetSerializerOptions()) as JsonSerializerSettings);
}
/// <summary>
/// 反序列化字符串
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="json"></param>
/// <param name="jsonSerializerOptions"></param>
/// <returns></returns>
public T Deserialize<T>(string json, object jsonSerializerOptions = null)
{
return JsonConvert.DeserializeObject<T>(json, (jsonSerializerOptions ?? GetSerializerOptions()) as JsonSerializerSettings);
}
/// <summary>
/// 反序列化字符串
/// </summary>
/// <param name="json"></param>
/// <param name="returnType"></param>
/// <param name="jsonSerializerOptions"></param>
/// <returns></returns>
public object Deserialize(string json, Type returnType, object jsonSerializerOptions = null)
{
return JsonConvert.DeserializeObject(json, returnType, (jsonSerializerOptions ?? GetSerializerOptions()) as JsonSerializerSettings);
}
/// <summary>
/// 返回读取全局配置的 JSON 选项
/// </summary>
/// <returns></returns>
public object GetSerializerOptions()
{
return App.GetOptions<MvcNewtonsoftJsonOptions>()?.SerializerSettings;
}
}
23.5.2 序列化属性名大写(属性原样输出)
System.Text.Json方式
services.AddControllersWithViews()
.AddJsonOptions(options => {
options.JsonSerializerOptions.PropertyNamingPolicy = null;
// options.JsonSerializerOptions.DictionaryKeyPolicy = null; // 配置 Dictionary 类型序列化输出
});
Newtonsoft.Json方式
services.AddControllersWithViews()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
特别注意采用 Newtonsoft.Json 方式接口返回值能够正常输出,但是 Swagger 界面中的 Example Values 依然显示小写字母开头的属性,这时只需要再添加 System.Text.Json 配置即可,如:
.AddJsonOptions(options => {
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
主要原因是 Swagger 拓展包底层依赖了 System.Text.Json。
23.5.3 时间格式化(时间戳转时间)
System.Text.Json方式
需引用 System.Text.Json 命名空间。
services.AddControllersWithViews()
.AddJsonOptions(options =>
{
// 在 Furion 4.6.5+ 支持,Furion 4.9.1.31+ 参数默认值为:yyyy-MM-dd HH:mm:ss
options.JsonSerializerOptions.Converters.AddDateTimeTypeConverters("yyyy-MM-dd HH:mm:ss");
// Furion 4.6.5 之前版本使用
// options.JsonSerializerOptions.Converters.AddDateFormatString("yyyy-MM-dd HH:mm:ss");
});
UTC 时间说明如果使用了 UTC 时间格式,那么可以设置 .AddDateTimeTypeConverters("yyyy-MM-dd HH:mm:ss", true) 第二个参数为 true,自动转换成本地时间。
如果使用了 Mysql 数据库,且使用了 Pomelo.EntityFrameworkCore.MySql 包,那么会出现时区问题,比如少 8 小时,可以尝试配置第二个参数为 true。
Newtonsoft.Json方式
需引用 Newtonsoft.Json 命名空间。
services.AddControllersWithViews()
.AddNewtonsoftJson(options =>
{
// 在 Furion 4.9.1.3+ 支持,Furion 4.9.1.31+ 参数默认值为:yyyy-MM-dd HH:mm:ss
options.SerializerSettings.Converters.AddDateTimeTypeConverters("yyyy-MM-dd HH:mm:ss");
// Furion 4.9.1.3 之前版本使用
// options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
});
时间戳转时间类型在 Furion 4.9.1.3+ 版本中,该操作还支持自动将 13/10 位时间戳数值或字符串转换成 DateTime/DateTime?/DateTimeOffset/DateTimeOffset? 类型。
如将 1699459200000 时间戳转换为 DateTime 类型。
针对 GET/HEAD 请求可通过贴 [ModelBinder(BinderType = typeof(TimestampToDateTimeModelBinder))] 特性处理。
23.5.4 忽略循环引用
System.Text.Json方式
services.AddControllersWithViews()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
});
特别说明在 .NET 5 中,System.Text.Json 并不支持处理循环引用问题,以上的解决方案仅限用于 .NET 6 Preview 2+。😂
需引用 System.Text.Json 命名空间。
Newtonsoft.Json方式
services.AddControllersWithViews()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
23.5.5 包含成员字段序列化
System.Text.Json方式
services.AddControllersWithViews()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.IncludeFields = true;
});
需引用 System.Text.Json 命名空间。
Newtonsoft.Json方式
无需配置。
23.5.6 允许尾随逗号
System.Text.Json方式
services.AddControllersWithViews()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.AllowTrailingCommas = true;
});
需引用 System.Text.Json 命名空间。
Newtonsoft.Json方式
无需配置。
23.5.7 允许注释
System.Text.Json方式
services.AddControllersWithViews()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.ReadCommentHandling = JsonCommentHandling.Skip;
});
需引用 System.Text.Json 命名空间。
Newtonsoft.Json方式
无需配置。
23.5.8 处理(中文)乱码问题
默认情况下,若序列化对象包含中文或特殊字符会被转义,如:
{
"statusCode": 500,
"data": null,
"succeeded": false,
"errors": "\u8BF7\u6C42\u53C2\u6570ips\u4E0D\u5141\u8BB8\u4E3A\u7A7A\uFF01",
"extras": null,
"timestamp": 1698390015
}
这时只需要通过下面配置即可:
System.Text.Json方式
services.AddControllersWithViews()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
});
需引用 System.Text.Json 命名空间。
Newtonsoft.Json方式
无需配置。
23.5.9 不区分大小写
System.Text.Json方式
services.AddControllersWithViews()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
});
需引用 System.Text.Json 命名空间。
Newtonsoft.Json方式
更多序列化配置这里只列举常用见的序列化配置,如需查看更多配置,可查阅 System.Text.Json 文档
23.5.10 忽略特定属性序列化
有时候我们不希望对象中某个对象被序列化出来或者不想在 Swagger 中显示,这时候只需要在属性贴该特性即可:
[Newtonsoft.Json.JsonIgnore] // 针对 Newtonsoft
[System.Text.Json.Serialization.JsonIgnore] // 针对 System.Text.Json
public string PropertyName {get; set;}
23.5.11 动态对象属性名大写问题
有时候使用了动态对象后发现属性名出现了大写情况(首字母),这个时候可以尝试使用以下方法解决:
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
})
23.5.12 忽略所有 null 属性
System.Text.Json方式
services.AddControllersWithViews()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
});
Newtonsoft.Json方式
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
})
23.5.13 忽略所有默认值属性
System.Text.Json方式
services.AddControllersWithViews()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault;
});
Newtonsoft.Json方式
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.DefaultValueHandling = DefaultValueHandling.Ignore;
})
23.5.14 控制属性序列化顺序
[Newtonsoft.Json.JsonProperty(Order = 0)] // 针对 Newtonsoft
[System.Text.Json.Serialization.JsonPropertyOrder(0)] // 针对 System.Text.Json
public string PropertyName {get; set;}
23.5.15 重命名序列化名称(属性名称)
[Newtonsoft.Json.JsonProperty("newName")] // 针对 Newtonsoft
[System.Text.Json.Serialization.JsonPropertyName("newName")] // 针对 System.Text.Json
public string PropertyName {get; set;}
23.5.16 JSON 字符串缩进
System.Text.Json方式
services.AddControllersWithViews()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.WriteIndented = true;
});
Newtonsoft.Json方式
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
})
23.5.17 long 类型序列化时转 string
有时候我们需要将 long 类型序列化时转为 string 类型,防止 JavaScript 出现精度溢出问题,这个时候可以尝试使用以下方法解决:
System.Text.Json方式
services.AddControllersWithViews()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.AddLongTypeConverters();
// options.JsonSerializerOptions.Converters.AddLongTypeConverters(overMaxLengthOf17: true); // Furion 4.9.1.23+ 可配置超过 17 位再转换
});
Newtonsoft.Json方式
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.Converters.AddLongTypeConverters();
// options.SerializerSettings.Converters.AddLongTypeConverters(overMaxLengthOf17: true); // Furion 4.9.1.23+ 可配置超过 17 位再转换
})
关于 Dictionary<,> 类型包含 long 处理默认情况下,System.Text.Json 不支持 Dictionary<,> 类型的序列化设置 Converter 操作,这个时候可以换成 Newtonsoft.Json 处理,如:
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.Converters.AddLongTypeConverters();
})
同时创建 NewtonsoftJsonSerializerProvider.cs 文件写入即可:
namespace YourProject.Core;
public class NewtonsoftJsonSerializerProvider : IJsonSerializerProvider, ISingleton
{
public string Serialize(object value, object jsonSerializerOptions = null)
{
return JsonConvert.SerializeObject(value, (jsonSerializerOptions ?? GetSerializerOptions()) as JsonSerializerSettings);
}
public T Deserialize<T>(string json, object jsonSerializerOptions = null)
{
return JsonConvert.DeserializeObject<T>(json, (jsonSerializerOptions ?? GetSerializerOptions()) as JsonSerializerSettings);
}
public object GetSerializerOptions()
{
return App.GetOptions<MvcNewtonsoftJsonOptions>()?.SerializerSettings;
}
public object Deserialize(string json, Type returnType, object jsonSerializerOptions = null)
{
return JsonConvert.DeserializeObject(json, returnType, (jsonSerializerOptions ?? GetSerializerOptions()) as JsonSerializerSettings);
}
}
23.5.18 DateOnly 和 TimeOnly 类型序列化支持
在 .NET6+ 添加了 DateOnly 和 TimeOnly 类型,Furion 4.7.9+ 提供了支持。
System.Text.Json方式
services.AddControllersWithViews()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.AddDateOnlyConverters(); // DateOnly
options.JsonSerializerOptions.Converters.AddTimeOnlyConverters(); // TimeOnly
});
Newtonsoft.Json方式
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.Converters.AddDateOnlyConverters(); // DateOnly
options.SerializerSettings.Converters.AddTimeOnlyConverters(); // TimeOnly
})
23.5.19 粘土对象 Clay 类型序列化支持
默认情况下,Clay 为动态类型对象,不支持直接通过 System.Text.Json 和 Newtonsoft.Json 进行序列化和反序列化,这时只需添加以下配置即可。
System.Text.Json方式
services.AddControllersWithViews()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.AddClayConverters();
});
Newtonsoft.Json方式
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.Converters.AddClayConverters();
})
23.5.20 DateTimeOffset 反序列化异常
以下处理只针对 Newtonsoft.Json,数据为 0001-01-01 00:00:00 的情形下反序列化为 DateTimeOffset 类型报错:
Could not convert string to DateTimeOffset: 0001-01-01 00:00:00
System.Text.Json方式
无需配置
Newtonsoft.Json方式
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.MetadataPropertyHandling = MetadataPropertyHandling.Ignore;
options.SerializerSettings.DateParseHandling = DateParseHandling.None;
options.SerializerSettings.Converters.Add(new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal });
});
23.5.21 继承/派生类序列化问题
在 .NET7 之前,System.Text.Json 默认不支持序列化基类属性,但也提供了解决方法:
// 第一种,使用 <object> 泛型
var json = JsonSerializer.Serialize<object>(value);
// 第二种,使用 Type 参数
var json = JsonSerializer.Serialize(value, value.GetType());
23.5.22 枚举和字符串互转问题
默认情况下,只能将枚举转换为数字或将数字转换为枚举对象,我们也可以通过局部或全局配置实现字符串互转,如:
- 局部
[JsonConverter(typeof(JsonStringEnumConverter))]
public Gender Gender { get; set; }
- 全局
services.AddControllersWithViews()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
});
23.5.23 检查 JSON 有效性
- 原生方式
try
{
using var document = JsonDocument.Parse(jsonString);
Console.WriteLine("正确");
}
catch (JsonException ex)
{
Console.WriteLine("错误");
}
JSON静态类方式
bool isValid = JSON.IsValid(jsonString); // furion 4.9.1.8+支持
23.5.24 自定义类型序列化转换器
在一些特殊的情况下,可能需要对特定的类型如 long 类型进行特殊处理,这时候就需要用到序列化转换器,如:
System.Text.Json方式
public class LongToStringJsonConverter : JsonConverter<long>
{
public override long Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return reader.GetInt64();
}
public override void Write(Utf8JsonWriter writer, long value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}
之后可通过 [JsonConverter(typeof(LongToStringJsonConverter))] 特性使用或者 全局使用:
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new LongToStringJsonConverter());
})
Newtonsoft.Json方式
public class LongToStringJsonConverter : JsonConverter<long>
{
public override long ReadJson(JsonReader reader, Type objectType, long existingValue, bool hasExistingValue, JsonSerializer serializer)
{
var jt = JValue.ReadFrom(reader);
return jt.Value<long>();
}
public override void WriteJson(JsonWriter writer, long value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString());
}
}
之后可通过 [JsonConverter(typeof(LongToStringJsonConverter))] 特性使用或者 全局使用:
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.Converters.Add(new LongToStringJsonConverter());
})
可空类型转换器自定义序列化转换器需要具体到具体的类型,也就是说 long 和 long? 是两个类型 ,如果需要处理,那么就需要创建两个自定义序列化转换器 JsonConverter<long> 和 JsonConverter<long?>。
23.6 DataTable、DataSet、Tuple 、JArray,JObject,JToken 等序列化问题
由于 Furion 默认采用 System.Text.Json 进行序列化,但是不支持复杂类型,如 DataTable、DataSet、Tuple 、JArray,JObject、JToken 等类型,所以需要更换成 NewtonsoftJson 即可,见 JSON 序列化 - 23.5.1 自定义序列化提供器
23.7 System.Text.Json 和 Newtonsoft.Json 完整差异化对比
23.8 反馈与建议
与我们交流给 Furion 提 Issue。